<template>
  <div class="h-full flex flex-col bg-white relative">
    <!-- 标题栏 -->
    <div class="flex items-center justify-between px-4 py-2.5 border-b border-gray-200 bg-gray-50 flex-shrink-0">
      <span class="text-sm font-medium text-gray-700">调试输出</span>
      <el-button
        type="text"
        icon="el-icon-delete"
        size="small"
        class="!text-gray-500 hover:!text-red-600"
        @click="handleClear"
      >
        清空
      </el-button>
    </div>

    <!-- 过滤和搜索工具栏 -->
    <div class="px-4 py-2 border-b border-gray-200 bg-white flex-shrink-0">
      <div class="flex items-center gap-3">
        <!-- 级别过滤 -->
        <div class="flex items-center gap-1">
          <el-button
            size="mini"
            :type="activeFilter === 'all' ? 'primary' : ''"
            @click="activeFilter = 'all'"
          >
            全部 ({{ logs.length }})
          </el-button>
          <el-button
            size="mini"
            :type="activeFilter === 'info' ? 'primary' : ''"
            @click="activeFilter = 'info'"
          >
            <i class="el-icon-info text-blue-400"></i> Info ({{ getLogCountByType('info') }})
          </el-button>
          <el-button
            size="mini"
            :type="activeFilter === 'stdout' ? 'primary' : ''"
            @click="activeFilter = 'stdout'"
          >
            <i class="el-icon-document text-teal-500"></i> Stdout ({{ getLogCountByType('stdout') }})
          </el-button>
          <el-button
            size="mini"
            :type="activeFilter === 'stderr' ? 'primary' : ''"
            @click="activeFilter = 'stderr'"
          >
            <i class="el-icon-warning text-yellow-500"></i> Stderr ({{ getLogCountByType('stderr') }})
          </el-button>
          <el-button
            size="mini"
            :type="activeFilter === 'error' ? 'primary' : ''"
            @click="activeFilter = 'error'"
          >
            <i class="el-icon-circle-close text-red-500"></i> Error ({{ getLogCountByType('error') }})
          </el-button>
        </div>

        <!-- 搜索框 -->
        <div class="flex-1">
          <el-input
            v-model="searchKeyword"
            placeholder="搜索日志内容..."
            size="small"
            clearable
            prefix-icon="el-icon-search"
            style="max-width: 300px"
          >
          </el-input>
        </div>

        <!-- 搜索结果统计 -->
        <div v-if="searchKeyword" class="text-xs text-gray-500">
          找到 {{ filteredLogs.length }} 条结果
        </div>
      </div>
    </div>

    <!-- 滚动到底部提示按钮 -->
    <transition name="fade">
      <div
        v-if="userScrolledUp"
        class="absolute bottom-4 left-1/2 transform -translate-x-1/2 z-10"
      >
        <el-button
          type="primary"
          size="small"
          icon="el-icon-bottom"
          @click="scrollToBottomAndResume"
          class="shadow-lg"
        >
          有新日志 · 点击滚动到底部
        </el-button>
      </div>
    </transition>

    <div class="flex-1 overflow-y-auto p-3 font-mono text-xs leading-relaxed output-content" ref="outputContent">
      <div
        v-if="logs.length === 0"
        class="flex flex-col items-center justify-center h-full text-gray-400"
      >
        <i class="el-icon-document text-5xl mb-2 opacity-50"></i>
        <p class="text-sm m-0">暂无输出日志</p>
      </div>

      <div
        v-else-if="filteredLogs.length === 0"
        class="flex flex-col items-center justify-center h-full text-gray-400"
      >
        <i class="el-icon-search text-5xl mb-2 opacity-50"></i>
        <p class="text-sm m-0">没有找到匹配的日志</p>
      </div>

      <div
        v-for="(log, index) in filteredLogs"
        :key="index"
        class="flex items-start px-2 py-1 mb-0.5 rounded transition-colors hover:bg-gray-50"
        :class="{
          'bg-red-50': log.type === 'error'
        }"
      >
        <span class="text-gray-400 mr-2.5 flex-shrink-0 text-[11px] select-none">{{ formatTime(log.timestamp) }}</span>
        <span class="mr-2 flex-shrink-0 text-sm" :class="{
          'text-teal-500': log.type === 'stdout',
          'text-yellow-500': log.type === 'stderr',
          'text-red-500': log.type === 'error',
          'text-blue-400': log.type === 'info'
        }">
          <i :class="getTypeIcon(log.type)"></i>
        </span>
        <span class="flex-1 break-all whitespace-pre-wrap" :class="{
          'text-gray-700': log.type !== 'error',
          'text-red-600': log.type === 'error'
        }" v-html="highlightKeyword(log.content)"></span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'OutputPanel',
  props: {
    logs: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      userScrolledUp: false, // 用户是否手动向上滚动
      activeFilter: 'all', // 当前激活的过滤器：all/info/stdout/stderr/error
      searchKeyword: '' // 搜索关键字
    }
  },
  computed: {
    // 过滤后的日志列表
    filteredLogs() {
      let logs = this.logs

      // 按类型过滤
      if (this.activeFilter !== 'all') {
        logs = logs.filter(log => log.type === this.activeFilter)
      }

      // 按关键字搜索
      if (this.searchKeyword && this.searchKeyword.trim()) {
        const keyword = this.searchKeyword.trim().toLowerCase()
        logs = logs.filter(log => {
          return log.content && log.content.toLowerCase().includes(keyword)
        })
      }

      return logs
    }
  },
  watch: {
    logs: {
      handler() {
        // 只有在用户未手动向上滚动时才自动滚动到底部
        if (!this.userScrolledUp) {
          this.$nextTick(() => {
            this.scrollToBottom()
          })
        }
      },
      deep: true
    }
  },
  mounted() {
    // 监听滚动事件,检测用户是否手动滚动
    const container = this.$refs.outputContent
    if (container) {
      container.addEventListener('scroll', this.handleScroll)
    }
  },
  beforeDestroy() {
    // 清理滚动事件监听
    const container = this.$refs.outputContent
    if (container) {
      container.removeEventListener('scroll', this.handleScroll)
    }
  },
  methods: {
    handleClear() {
      this.$emit('clear')
      // 清空后重置滚动状态
      this.userScrolledUp = false
    },

    handleScroll() {
      const container = this.$refs.outputContent
      if (!container) return

      // 计算是否滚动到底部 (允许5px的误差)
      const isAtBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 5

      // 如果用户滚动到底部,取消"手动向上滚动"状态
      if (isAtBottom) {
        this.userScrolledUp = false
      } else {
        // 如果用户向上滚动,标记状态
        this.userScrolledUp = true
      }
    },

    scrollToBottom() {
      const container = this.$refs.outputContent
      if (container) {
        container.scrollTop = container.scrollHeight
      }
    },

    scrollToBottomAndResume() {
      // 恢复自动滚动
      this.userScrolledUp = false
      // 滚动到底部
      this.$nextTick(() => {
        this.scrollToBottom()
      })
    },

    formatTime(timestamp) {
      if (!timestamp) return ''
      const date = new Date(timestamp)
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      const seconds = String(date.getSeconds()).padStart(2, '0')
      const milliseconds = String(date.getMilliseconds()).padStart(3, '0')
      return `${hours}:${minutes}:${seconds}.${milliseconds}`
    },

    getTypeIcon(type) {
      const icons = {
        stdout: 'el-icon-document',
        stderr: 'el-icon-warning',
        error: 'el-icon-circle-close',
        info: 'el-icon-info'
      }
      return icons[type] || 'el-icon-document'
    },

    // 获取指定类型的日志数量
    getLogCountByType(type) {
      return this.logs.filter(log => log.type === type).length
    },

    // 高亮显示搜索关键字
    highlightKeyword(content) {
      if (!this.searchKeyword || !this.searchKeyword.trim() || !content) {
        return this.escapeHtml(content)
      }

      const keyword = this.searchKeyword.trim()
      const escapedContent = this.escapeHtml(content)
      const escapedKeyword = this.escapeHtml(keyword)

      // 使用正则表达式进行不区分大小写的替换
      const regex = new RegExp(`(${escapedKeyword})`, 'gi')
      return escapedContent.replace(regex, '<mark class="bg-yellow-200 text-gray-900 px-0.5">$1</mark>')
    },

    // HTML 转义，防止 XSS 攻击
    escapeHtml(text) {
      if (!text) return ''
      const div = document.createElement('div')
      div.textContent = text
      return div.innerHTML
    }
  }
}
</script>

<style scoped>
/* 使用全局滚动条样式 */

/* 淡入淡出动画 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s, transform 0.3s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
  transform: translate(-50%, 10px);
}
</style>
